#include <stdint.h>
#include "HelloWorld.h"

#include <uxr/client/client.h>
#define STREAM_HISTORY  8
#define BUFFER_SIZE     UXR_CONFIG_UDP_TRANSPORT_MTU* STREAM_HISTORY
uint8_t output_reliable_stream_buffer[BUFFER_SIZE];
uint8_t input_reliable_stream_buffer[BUFFER_SIZE];
uint8_t output_besteffort_stream_buffer[BUFFER_SIZE];
uint32_t sub_xcre_counter = 0;
uint8_t sub_xcre_step = 0;
static  uxrUDPTransport XCRE_transport;
static  uxrSession XCRE_session;
HelloWorld topic_data;
void on_topic(
        uxrSession* session,
        uxrObjectId object_id,
        uint16_t request_id,
        uxrStreamId stream_id,
        struct ucdrBuffer* ub,
        uint16_t length,
        void* args)
{
    (void) session; (void) object_id; (void) request_id; (void) stream_id; (void) length;

    HelloWorld_deserialize_topic(ub, &topic_data);
    sub_xcre_counter++;
}
uxrStreamId reliable_out;
uxrStreamId reliable_in;
uxrStreamId besteffort_out;
uxrStreamId besteffort_in;
uxrObjectId participant_id = {0x01,UXR_PARTICIPANT_ID};
uxrObjectId topic_id       = {0x01,UXR_TOPIC_ID};
uxrObjectId sub_id         = {0x01,UXR_SUBSCRIBER_ID};
uxrObjectId datareader_id  = {0x01,UXR_DATAREADER_ID};
uxrQoS_t  qos = {.reliability = UXR_RELIABILITY_BEST_EFFORT,.durability=UXR_DURABILITY_TRANSIENT_LOCAL,
                 .history=UXR_HISTORY_KEEP_LAST,.depth=0};
char topic_name[20] = "TestTopic";
char type_name[12] = "Test";
void Create_Transport(void)
{
    char* ip = "192.168.0.10";
    char* port =  "12345";
    uxrUDPTransport transport;
    if (uxr_init_udp_transport(&XCRE_transport, UXR_IPv4, ip, port))
    {
        uxr_init_session(&XCRE_session, &XCRE_transport.comm, 0xCCCCDDDD);
        uxr_set_topic_callback(&XCRE_session, on_topic, NULL);
    }
}

uint8_t Create_session(void)
{
    if (uxr_create_session(&XCRE_session))
    {

        reliable_out = uxr_create_output_reliable_stream(&XCRE_session, output_reliable_stream_buffer, BUFFER_SIZE,
                        STREAM_HISTORY);
        reliable_in = uxr_create_input_reliable_stream(&XCRE_session, input_reliable_stream_buffer, BUFFER_SIZE,
                        STREAM_HISTORY);
        besteffort_out = uxr_create_output_best_effort_stream(&XCRE_session, output_besteffort_stream_buffer, BUFFER_SIZE);
        besteffort_in = uxr_create_input_best_effort_stream(&XCRE_session);
        return 1;
    }
    return 0;
}

uint16_t participant_create_id,topic_create_id,sub_create_id,datareader_create_id;
void Create_Object(void)
{
    participant_create_id = uxr_buffer_create_participant_bin(&XCRE_session,besteffort_out,participant_id,0,NULL,UXR_REPLACE);
    topic_create_id   = uxr_buffer_create_topic_bin(&XCRE_session,besteffort_out,topic_id,participant_id,topic_name,type_name,UXR_REPLACE);
    sub_create_id     = uxr_buffer_create_subscriber_bin(&XCRE_session,besteffort_out,sub_id,participant_id,UXR_REPLACE);
    datareader_create_id = uxr_buffer_create_datareader_bin(&XCRE_session,besteffort_out,datareader_id,sub_id,topic_id,qos,UXR_REPLACE);
    uxr_flash_output_streams(&XCRE_session);
}

void Sub_Data(void)
{
    uxrDeliveryControl dc = {0};
    dc.max_samples = UXR_MAX_SAMPLES_UNLIMITED;
    uxr_buffer_request_data(&XCRE_session,besteffort_out,datareader_id,besteffort_in,&dc);
    uxr_flash_output_streams(&XCRE_session);
}

void Run_Session(void)
{
    uxr_run_session_time(&XCRE_session,0);
}

void XCRE_MainFunction(void)
{
    switch(sub_xcre_step)
    {
        case 0:
        {
            Create_Transport();
            sub_xcre_step = 1;
            break;
        }
        case 1:
        {
            if(1 == Create_session())
            {
                sub_xcre_step = 2;
            }
            break;
        }
        case 2:
        {
            Create_Object();
            Sub_Data();
            sub_xcre_step = 3;
            break;
        }
        case 3:
        {
            Run_Session();
            break;
        }
    }
}